import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; import "react-loading-skeleton/dist/skeleton.css"; import { ClockIcon, HeartIcon } from "@heroicons/react/20/solid"; import { TvIcon, ArrowTrendingUpIcon, RectangleStackIcon, } from "@heroicons/react/24/outline"; import Head from "next/head"; import Image from "next/image"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; import Layout from "../../components/layout"; import Link from "next/link"; import Content from "../../components/hero/content"; import Modal from "../../components/modal"; import { signIn, useSession } from "next-auth/react"; import AniList from "../../components/media/aniList"; import ListEditor from "../../components/listEditor"; const query = ` query ($username: String, $status: MediaListStatus) { MediaListCollection(userName: $username, type: ANIME, status: $status, sort: SCORE_DESC) { user { id name about (asHtml: true) createdAt avatar { large } statistics { anime { count episodesWatched meanScore minutesWatched } } bannerImage mediaListOptions { animeList { sectionOrder } } } lists { status name entries { id mediaId status progress score media { id status title { english romaji } episodes coverImage { large } } } } } } `; const infoQuery = `query ($id: Int) { Media(id: $id) { id type title { romaji english native } coverImage { extraLarge large color } bannerImage description episodes nextAiringEpisode { episode airingAt } averageScore popularity status startDate { year } duration genres relations { edges { relationType node { id type status title { romaji english userPreferred } coverImage { extraLarge large color } } } } recommendations { nodes { mediaRecommendation { id title { romaji } coverImage { extraLarge large } } } } } }`; const stats = [ "Watching", "Plan to Watch", "Completed", "Dropped", "Paused", "Rewatching", ]; export default function Info() { const { data: session, status } = useSession(); const [data, setData] = useState(null); const [info, setInfo] = useState(null); const [episode, setEpisode] = useState(null); const [loading, setLoading] = useState(false); const [progress, setProgress] = useState(0); const [statuses, setStatuses] = useState(null); const [stall, setStall] = useState(false); const [color, setColor] = useState(null); const [showAll, setShowAll] = useState(false); const [open, setOpen] = useState(false); const [time, setTime] = useState(0); const { id } = useRouter().query; const [aniStatus, setAniStatus] = useState(statuses); const [aniProgress, setAniProgress] = useState(0); const [epiStatus, setEpiStatus] = useState("ok"); const rec = info?.recommendations?.nodes.map( (data) => data.mediaRecommendation ); // const [log, setLog] = useState(null); useEffect(() => { const defaultState = { data: null, info: null, episode: null, loading: true, statuses: null, progress: null, stall: false, EpiStatus: "ok", }; // Reset all state variables to their default values Object.keys(defaultState).forEach((key) => { const value = defaultState[key]; if (Array.isArray(value)) { value.length ? eval( `set${ key.charAt(0).toUpperCase() + key.slice(1) }(${JSON.stringify(value)})` ) : eval(`set${key.charAt(0).toUpperCase() + key.slice(1)}([])`); } else { eval( `set${key.charAt(0).toUpperCase() + key.slice(1)}(${JSON.stringify( value )})` ); } }); async function fetchData() { if (id) { setLoading(false); try { const [res, info] = await Promise.all([ fetch(`https://api.moopa.my.id/meta/anilist/info/${id?.[0]}`), fetch("https://graphql.anilist.co/", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ query: infoQuery, variables: { id: id?.[0], }, }), }), ]); const data = await res.json(); const infos = await info.json(); setInfo(infos.data.Media); // setLog(data); const textColor = setTxtColor(infos.data.Media.coverImage?.color); if (!data || data.episodes.length === 0) { const res = await fetch( `https://api.consumet.org/meta/anilist/info/${id[0]}?provider=9anime` ); const datas = await res.json(); if (res.status === 500) { setEpisode(null); setEpiStatus("error"); } else { setEpisode(datas.episodes); } setColor({ backgroundColor: `${data?.color || "#ffff"}`, color: textColor, }); setStall(true); } else { setEpisode(data.episodes); } setColor({ backgroundColor: `${data?.color || "#ffff"}`, color: textColor, }); if (session?.user?.name) { const response = await fetch("https://graphql.anilist.co/", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ query: query, variables: { username: session?.user?.name, }, }), }); const dat = await response.json(); const prog = dat.data.MediaListCollection; const gat = prog.lists.map((item) => item.entries); const git = gat.map((item) => item.find((item) => item.media.id === parseInt(data?.id)) ); const gut = git?.find( (item) => item?.media.id === parseInt(data?.id) ); if (gut) { setProgress(gut?.progress); setAniProgress(parseInt(gut?.progress)); if (gut.status === "CURRENT") { setStatuses("Watching"); setAniStatus("Watching"); } else if (gut.status === "PLANNING") { setStatuses("Plan to watch"); setAniStatus("Plan to watch"); } else if (gut.status === "COMPLETED") { setStatuses("Completed"); setAniStatus("Completed"); } else if (gut.status === "DROPPED") { setStatuses("Dropped"); setAniStatus("Dropped"); } else if (gut.status === "PAUSED") { setStatuses("Paused"); setAniStatus("Paused"); } else if (gut.status === "REPEATING") { setStatuses("Rewatching"); setAniStatus("Rewatching"); } } } if (data.nextAiringEpisode) { setTime( convertSecondsToTime(data.nextAiringEpisode.timeUntilAiring) ); } setData(data); setLoading(true); } catch (error) { console.log(error); setTimeout(() => { window.location.reload(); }, 1000); } } } fetchData(); }, [id, session?.user?.name]); function handleOpen() { setOpen(true); document.body.style.overflow = "hidden"; } function handleClose() { setOpen(false); document.body.style.overflow = "auto"; } function handleSubmit(e) { e.preventDefault(); const formData = { status: aniStatus, progress: aniProgress }; console.log(formData); } function handleProgress(e) { setAniProgress(e.target.value); } // console.log(progress); return ( <> {info ? info?.title?.romaji || info?.title?.english : "Retrieving Data..."} handleClose()}>
{!session && (

Edit your list

)} {session && loading && ( )}
{info ? ( banner anime ) : (
)}
{/* Mobile */}

{/* Yuru Campā–³ SEASON 2 */} {info?.title?.romaji || info?.title?.english}

{info?.genres ?.slice( 0, info?.genres?.length > 3 ? info?.genres?.length : 3 ) .map((item, index) => ( {item} {/* {index !== info?.genres?.length - 1 && ( )} */} ))}
{info && (
)}
{info && info.status !== "NOT_YET_RELEASED" ? ( <>

{info?.type}

{info?.averageScore}%

{info?.episodes} Episodes

) : (
{info && "Not Yet Released"}
)}
{/* PC */}
{info ? ( <>
poster anime ) : ( )}
{/* PC */}

{info ? ( info?.title?.romaji || info?.title?.english ) : ( )}

{info ? (
{info?.episodes} Episodes
{info?.startDate?.year}
{info?.averageScore}%
{info?.type}
{info?.status}
Sub | EN
) : ( )}
{info ? (

) : ( )}

{info && (
Relations
)} {info?.relations?.edges?.length > 3 && (
setShowAll(!showAll)} > {showAll ? "show less" : "show more"}
)}
{info?.relations?.edges ? ( info?.relations?.edges .slice(0, showAll ? info?.relations?.edges.length : 3) .map((r, index) => { const rel = r.node; return (
{rel.id}
{r.relationType}
{rel.title.userPreferred || rel.title.romaji}
{rel.type}
); }) ) : ( <> {[1, 2, 3].map((item) => (
))}
)}
{info && (

Episodes

)} {info?.nextAiringEpisode && (

Next Ep :

{time}
)}
{loading ? ( data && (
{epiStatus === "ok" ? ( episode?.length !== 0 ? ( episode?.map((epi, index) => { return (

Episode {epi.number}

{epi.title && (

"{epi.title}"

)} {index !== episode?.length - 1 && ( )}
); }) ) : (

No Episodes Available

) ) : (

Something went wrong, can't retrieve any episodes :/

)}
) ) : (
)}
{rec && (
)}
); } function convertSecondsToTime(sec) { let days = Math.floor(sec / (3600 * 24)); let hours = Math.floor((sec % (3600 * 24)) / 3600); let minutes = Math.floor((sec % 3600) / 60); let time = ""; if (days > 0) { time += `${days}d `; } if (hours > 0) { time += `${hours}h `; } if (minutes > 0) { time += `${minutes}m `; } return time.trim(); } function getBrightness(hexColor) { if (!hexColor) { return 200; } const rgb = hexColor .match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i) .slice(1) .map((x) => parseInt(x, 16)); return (299 * rgb[0] + 587 * rgb[1] + 114 * rgb[2]) / 1000; } function setTxtColor(hexColor) { const brightness = getBrightness(hexColor); return brightness < 150 ? "#fff" : "#000"; }